package com.ljw.servlet_springMVC.annotation.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.AsyncHandlerInterceptor;

import javax.servlet.AsyncListener;
import java.util.concurrent.Callable;

/**
 * @FileName AsyncHelloController
 * @Description TODO springMVC的 异步请求 处理
 * @Author ljw
 * @Date 2021/2/7 22:41
 * @Version 1.0
 */
@Controller
public class AsyncHelloController {


    /**
     * springMVC的 异步请求 处理方式1：
     *      1. 控制器方法返回Callable。
     *      2. Spring异步处理Callable，将Callable提交到TaskExecutor，使用一个隔离的线程进行处理Callable
     *      3. DispatcherServlet和所有的Filter退出servlet容器的线程，但response保持打开状态。
     *      4. 隔离的线程处理Callable完毕，然后返回结果，springmvc将返回的结果装入请求重新派发给servlet容器，恢复之前的处理
     *      5. 根据Callable返回的结果，springmvc继续进行视图渲染流程
     *
     *  打印结果：
     *       preHandle----------/async01
             主线程开始...http-nio-8080-exec-4===>1612712734840
             主线程结束...http-nio-8080-exec-4===>1612712734842
     ============3. DispatcherServlet和所有的Filter退出servlet容器的线程===================

     =========4. Callable开始执行，但Callable业务逻辑并没有真正被拦截器拦截===========
             副线程开始...MvcAsync1===>1612712734851
             副线程结束...MvcAsync1===>1612712737851
     =========Callable开始结束===========

     =========4. Callable完毕，然后返回结果，springmvc将返回的结果装入请求重新派发给servlet容器，恢复之前的处理========
             preHandle----------/async01
             postHandle----------
             afterCompletion----------


            问题：此种异步请求，其Callable的业务逻辑并没有真正被拦截器拦截。需要异步的拦截器。
            异步的拦截器2种：
                1. 实现原生servlet的api的javax.servlet.AsyncListener接口
                2. 实现springmvc的AsyncHandlerInterceptor接口
     * @return
     */
    @ResponseBody
    @RequestMapping("/async01")
    public Callable<String> async01(){
        System.out.println("主线程开始..."+Thread.currentThread().getName()+"===>"+System.currentTimeMillis());


        Callable<String> callable = new Callable<String>() {

            @Override
            public String call() throws Exception {
                System.out.println("副线程开始..." + Thread.currentThread().getName() + "===>" + System.currentTimeMillis());
                Thread.sleep(3000);
                System.out.println("副线程结束..." + Thread.currentThread().getName() + "===>" + System.currentTimeMillis());
                return "Callable<String> async01()";
            }
        };

        System.out.println("主线程结束..."+Thread.currentThread().getName()+"===>"+System.currentTimeMillis());

        return callable;
    }
}
